package com.scott.masterselector.zkclient;

import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;
import org.I0Itec.zkclient.exception.ZkNodeExistsException;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * master 选举
 *
 * @author Scott 2017/11/9 10:52
 */
public class MasterSelector {

    //ZkClient
    private ZkClient zkClient;

    //master节点名称
    private final static String MASTER_PATH = "/master";

    //服务节点
    private UserCenterService service;

    //master节点
    private UserCenterService master;

    //是否启动中
    private boolean isRunning = false;

    //节点数据监听
    private IZkDataListener listener;


    public MasterSelector(ZkClient zkClient, UserCenterService service) {
        this.zkClient = zkClient;
        this.service = service;
        System.out.println(service.getMcName() + ":服务链接");


        this.listener = new IZkDataListener() {
            @Override
            public void handleDataChange(String s, Object o) throws Exception {

            }

            //节点删除时间监听
            @Override
            public void handleDataDeleted(String s) throws Exception {
                System.out.println(service.getMcName() + ":捕获节点被删除事件" + s);
                chooseMaster();
            }
        };

    }

    /**
     * 启动选主监听
     */
    public void start() {
        if (!isRunning) {
            //向当前的client中注册事件监听
            this.zkClient.subscribeDataChanges(MASTER_PATH, listener);
            isRunning = true;
            chooseMaster();
        }
    }

    /**
     * 选主操作
     */
    private void chooseMaster() {
        if (!isRunning) {
            System.out.println("服务没有启动");
        }
        //尝试创建master节点 并捕获节点存在异常
        try {
            System.out.println(service.getMcName() + ":开始竞争，尝试创建master临时节点");
            zkClient.createEphemeral(MASTER_PATH, service);
            //成功则说明创建成功
            System.out.println(service.getMcName() + ":我已经是Master节点->" + service);
            master = service;
        } catch (ZkNodeExistsException e) {
            //节点已经存在

            UserCenterService userCenterService = zkClient.readData(MASTER_PATH, true);
            if (userCenterService == null) {
                System.out.println(this.service.getMcName() + ":没有获取到，再次重试");
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }
                chooseMaster();
            }
            System.out.println(service.getMcName() + ":节点已经存在了当前Master节点-> " + userCenterService);
        }

    }


    public void stopService() {
        System.out.println(service.getMcName() + ":停止master客户端 master信息为->" + this.master + " service 信息为 -> " + this.service);
        this.zkClient.close();
    }

    public UserCenterService getService() {
        return service;
    }

    public UserCenterService getMaster() {
        return master;
    }


}
